﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections;
using WebCrawlerTools.page;
using WebCrawlerTools.search;
using WebCrawlerTools.data;
using WebCrawlerTools.web;
using WebCrawlerTools.plugin;
using System.Reflection;
using WebCrawlerTools.form;
using WebCrawlerTools.control;

namespace WebCrawlerTools
{
    public partial class MainForm : Form, IPluginHost
    {
        private void btn_open_Click(object sender, EventArgs e)
        {
            //initialize Log
            Log.Inst().Path = dataCenter.BasicInfo.DataPath + "\\" + controlCenter.HomePage.Name;
            if (webwin.Document == null)
            {
                return;
            }
            if (controlCenter.HomePage == null)
            {
                return;
            }
            //controlCenter.EventInitialize();
            //controlCenter.StartEngine();
            timer1.Enabled = true;
        }
        //display page
        private void OnOnePageLoadCompleted(object sender, EventArgs e)
        {
            htmlwin.Text = enginer.Source;
            txt_url.Text = webwin.Url.ToString();
        }
        //-------------------------------------------------------------------------------------

        //-------------------------------------------------------------------------------------
        private ControlCenter controlCenter;
        private DataCenter dataCenter;
        private SEngine enginer = new SEngine();
        private Page currentPage;
        private IPlugin[] ipi;
        private ArrayList sLines = new ArrayList();

        public MainForm()
        {
            InitializeComponent();
        }

        #region Onload
        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            UI_Update_All(false);
            unload_plugin();
            DataCenter.Store(dataCenter);
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            WebEngine.Web = webwin;
            this.webwin.ProgressChanged += new System.Windows.Forms.WebBrowserProgressChangedEventHandler(enginer.Net.OnLoad);
            dataCenter = DataCenter.Load();
            controlCenterInit();
            UI_Update_All(true);
            init_plugin();
            //------------------------------
            enginer.ControlCenter = controlCenter;
            //display page
            enginer.OnePageLoadCompleted += new EventHandler(this.OnOnePageLoadCompleted);
            enginer.UIUpdate += new PageEventHandler(this.DisplayPage);
            enginer.UIDataUpdate += new PageDataEventHandler(this.DisplayPageData);
            controlCenter.Engine = enginer;
            enginer.HomePage = controlCenter.HomePage;
            //initailize Log
            Log.Inst().Path = dataCenter.BasicInfo.DataPath + "\\" + controlCenter.HomePage.Name;

        }
        private void controlCenterInit()
        {
            controlCenter = new ControlCenter();
            if (dataCenter.HomePages == null && dataCenter.HomePages.Count < 1)
            {
                return;
            }
            controlCenter.HomePage = (PHomePage)dataCenter.HomePages[0];
        }

        #endregion

        #region Plugin
        private void init_plugin()
        {
            string path = Application.StartupPath;
            string[] pluginFiles = Directory.GetFiles(path, "*.DLL");
            ipi = new IPlugin[pluginFiles.Length];

            for (int i = 0; i < pluginFiles.Length; i++)
            {
                string filename = pluginFiles[i].ToLower();
                string args = pluginFiles[i].Substring(
                    pluginFiles[i].LastIndexOf("\\") + 1,
                    pluginFiles[i].IndexOf(".dll") -
                    pluginFiles[i].LastIndexOf("\\") - 1);

                Type ObjType = null;
                try
                {
                    // load it
                    Assembly ass = null;
                    ass = Assembly.Load(args);
                    if (ass != null)
                    {
                        ObjType = ass.GetType(args + ".PlugIn");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                try
                {
                    if (ObjType != null)
                    {
                        ipi[i] = (IPlugin)Activator.CreateInstance(ObjType);
                        ipi[i].Host = this;
                        ipi[i].Onload();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
        public bool Register(IPlugin ipi)
        {
            cmb_plugin.Items.Add(ipi.Name);
            return true;
        }

        private void unload_plugin()
        {
            for (int i = 0; i < ipi.Length; i++)
            {
                ipi[i].OnClose();
            }
        }

        private void cmb_plugin_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmb_plugin.SelectedIndex >= 0)
            {
                ipi[cmb_plugin.SelectedIndex].Show(controlCenter);
            }
        }
        #endregion
        
        #region UI_Update
        private void DisplayPage(object sender, PageEventArgs e)
        {
            UI_Update_Page(true, e.Page);
        }
        private void DisplayPageData(object sender, PageDataEventArgs e)
        {
            displayData(e.Result);
        }
        private void UI_Update_Page(bool IsLoad,Page page)
        {
            if (page == null)
                return;
            if (IsLoad)
            {
                txt_url.Text = page.Url;
                tempwin.Text = page.Template.Replace("\n", "\r\n");
                if (page.Move != null)
                {
                    if (page.Move.Type == LoopType.URL)
                    {
                        rdo_url.Checked = true;
                    }
                    else
                    {
                        rdo_js.Checked = true;
                    }
                    txt_move_next.Text = page.Move.Template;
                }
                else
                {
                    txt_move_next.Text = "";
                    rdo_url.Checked = true;
                }
                formDataDisplay(page);
            }
            else
            {
                page.Url = txt_url.Text;
                page.Template = tempwin.Text.Replace("\r", "");
                page.Move = new PPageMove();
                if (rdo_url.Checked)
                {
                    page.Move.Type = LoopType.URL;
                }
                else if (rdo_js.Checked)
                {
                    page.Move.Type = LoopType.JavaScript;
                }
                else
                {
                    page.Move.Type = LoopType.Dynamic;
                }
                page.Move.Template = txt_move_next.Text;
            }
        }
        private void formDataDisplay(Page page)
        {
            if (page.PageType == PPageType.SEARCH_PAGE)
            {
                PSearchPage sp = (PSearchPage)page;
                lst_data.Columns.Clear();
                lst_data.Items.Clear();
                if (sp.Forms.Count > 0)
                {
                    lst_data.Columns.Add("Name", 50, HorizontalAlignment.Left);
                    lst_data.Columns.Add("ID", 50, HorizontalAlignment.Left);
                    lst_data.Columns.Add("Type", 50, HorizontalAlignment.Left);
                    lst_data.Columns.Add("Value", 50, HorizontalAlignment.Left);
                    foreach (HForm f in sp.Forms)
                    {
                        foreach (HElement he in f.Elements)
                        {

                            ListViewItem li = lst_data.Items.Add(he.Name);
                            li.SubItems.Add(he.ID);
                            li.SubItems.Add(he.Type.ToString());
                            li.SubItems.Add(he.Val);
                        }
                    }
                    foreach (ColumnHeader ch in lst_data.Columns)
                    {
                        ch.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
                    }
                }
            }
            else
            {
                lst_data.Columns.Clear();
                lst_data.Items.Clear();
            }
        }
        private void displayData(SResult result)
        {
            lst_data.Columns.Clear();
            lst_data.Items.Clear();
            if (result == null)
            {
                return;
            }
            foreach (String title in result.Title.Data)
            {
                lst_data.Columns.Add(title, 50, HorizontalAlignment.Left);
            }

            foreach (SLine sl in result.Data)
            {
                if (sl.Data.Count == 0)
                {
                    break;
                }
                ListViewItem li = lst_data.Items.Add((String)sl.Data[0]);
                for (int i = 1; i < sl.Data.Count; i++)
                {
                    li.SubItems.Add((String)sl.Data[i]);
                }
            }
            foreach (ColumnHeader ch in lst_data.Columns)
            {
                ch.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
            }
        }

        private void UI_Update_All(bool IsLoad)
        {
            if (IsLoad)
            {
                treeView1.BeginUpdate();
                treeView1.Nodes.Clear();
                foreach (PHomePage page in dataCenter.HomePages)
                {
                    TreeNode node = treeView1.Nodes.Add(page.Name);
                    node.Tag = page;
                    node.Nodes.Add(page.SearchPage.Name);
                    node.Nodes[0].Tag = page.SearchPage;
                    node.Nodes.Add(page.ListPage.Name);
                    node.Nodes[1].Tag = page.ListPage;
                    node.Nodes.Add(page.DetailPage.Name);
                    node.Nodes[2].Tag = page.DetailPage;
                }
                treeView1.EndUpdate();
                treeView1.ExpandAll();
                if (dataCenter.HomePages != null && dataCenter.HomePages.Count >= 1)
                {
                    currentPage = (PHomePage)dataCenter.HomePages[0];
                    UI_Update_Page(IsLoad, currentPage);
                }
            }
            else
            {
                //UI_Update_Page(IsLoad, dataCenter.Page);
            }
        }

        private void UI_Leave(object sender, EventArgs e)
        {
            UI_Update_Page(false, currentPage);
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                currentPage = (Page)treeView1.SelectedNode.Tag;
                UI_Update_Page(true, currentPage);
                if (currentPage.PageType == PPageType.HOME_PAGE)
                {
                    controlCenter.HomePage = (PHomePage)currentPage;
                }
                else
                {
                    controlCenter.HomePage = (PHomePage)treeView1.SelectedNode.Parent.Tag;
                }
            }
        }
        private void btn_edit_Click(object sender, EventArgs e)
        {
            DlgSystem dlg = new DlgSystem();
            dlg.DataPath = dataCenter.BasicInfo.DataPath;
            if (string.IsNullOrEmpty(dlg.DataPath))
            {
                dlg.DataPath = System.Environment.CurrentDirectory;
            }
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                dataCenter.BasicInfo.DataPath = dlg.DataPath;
            }
        }

        #endregion

        #region Tree Operate
        private void btn_add_Click(object sender, EventArgs e)
        {
            DlgSiteInfo sitedlg = new DlgSiteInfo();
            if (sitedlg.ShowDialog() == DialogResult.OK)
            {
                PHomePage page = new PHomePage();
                page.Name = sitedlg.SiteName;
                dataCenter.HomePages.Add(page);

                treeView1.BeginUpdate();
                TreeNode node = treeView1.Nodes.Add(sitedlg.SiteName);
                node.Tag = page;
                node.Nodes.Add(page.SearchPage.Name);
                node.Nodes[0].Tag = page.SearchPage;
                node.Nodes.Add(page.ListPage.Name);
                node.Nodes[1].Tag = page.ListPage;
                node.Nodes.Add(page.DetailPage.Name);
                node.Nodes[2].Tag = page.DetailPage;

                treeView1.EndUpdate();
            }
        }

        private void btn_del_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                TreeNode node = treeView1.SelectedNode;
                if (node.Text == "Sub Page")
                {
                    if (treeView1.SelectedNode.Parent != null)
                    {
                        node = treeView1.SelectedNode.Parent;
                    }
                }
                if (MessageBox.Show("Are you sure to delete " + node.Text + " ?", "Delete", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    PHomePage page = (PHomePage) node.Tag;
                    for(int i = 0 ; i<dataCenter.HomePages.Count;i++)
                    {
                        PHomePage p = (PHomePage)dataCenter.HomePages[i];
                        if (page.Name == p.Name)
                        {
                            dataCenter.HomePages.RemoveAt(i);
                            break;
                        }
                    }
                    treeView1.Nodes.Remove(node);
                }
            }
        }
        #endregion

        private void btn_url_Click(object sender, EventArgs e)
        {
            htmlwin.Text = "";
            enginer.DataCenter = dataCenter;
            enginer.Net.OpenUri(currentPage.Url);
        }

        //---------------------------
        //Data analysis
        private void btn_analysis_Click(object sender, EventArgs e)
        {
            SResult sr= SEngine.getData(enginer.Source, tempwin.Text);
            displayData(sr);
        }

        //Data Save
        private void button2_Click(object sender, EventArgs e)
        {
            //if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            //{
            //    DataCenter.ToCSV(enginer.PageEngine.Result.Data, saveFileDialog1.FileName);
            //}
        }

        //Get data
        private void btn_test_Click(object sender, EventArgs e)
        {
            if (currentPage.PageType == PPageType.SEARCH_PAGE)
            {
                PSearchPage searchpage = (PSearchPage)currentPage;
                searchpage.UpdateData(true,webwin.Document.Forms);
                formDataDisplay(searchpage);
            }
        }
        //Data input
        private void btn_form_load_Click(object sender, EventArgs e)
        {
            enginer.SearchPageInput();
        }
        //start Search 
        private void btn_detail_Click(object sender, EventArgs e)
        {
            enginer.SearchPageStartSearch();
        }
        //goto detail page
        private void btn_test1_Click(object sender, EventArgs e)
        {
            enginer.ListPageAnalysis();
            enginer.OpenDetailPage();
        }
        //go back list page
        private void btn_test2_Click(object sender, EventArgs e)
        {
            enginer.GoBackToListPage();
        }
        //next detail page
        private void btn_test3_Click(object sender, EventArgs e)
        {
            enginer.GoToNextDetailPage();
        }
        //list page's next page
        private void btn_next_page_Click(object sender, EventArgs e)
        {
            enginer.GoToNextListPage();
        }

        private void btn_test4_Click(object sender, EventArgs e)
        {
            enginer.DetailPageAnalysis();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            enginer.ListPageAnalysis();
            enginer.GoToNextListPage();
        }
    }
}